﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Kinect;

namespace Microsoft.Samples.Kinect.WpfViewers {
    class KinectRun : KinectMovement {
        
        [DllImport("user32.dll", EntryPoint = "keybd_event", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern void Keybd_event(byte vk, byte scan, int flags, int extrainfo);

        public float LeftBaseline;
        public float RightBaseline;
        
        public float RightCurrent;
        public float LeftCurrent;

        public float RightKnee;
        public float LeftKnee;

        public bool RightUp = false;
        public bool LeftUp = false;

        public bool Run = false;
        public bool Jump = false;

        public bool MoveRight = false;
        public bool MoveLeft = false;

        public bool Punch = false;
        public bool Use = false;
        public DateTime PunchStart = DateTime.Now;

        public bool Duck = false;

        protected TimeSpan JumpTP = new TimeSpan();
        public DateTime JumpStart = DateTime.Now;

        InputStruct gas = new InputStruct();
        InputStruct left = new InputStruct();
        InputStruct right = new InputStruct();
        InputStruct jump = new InputStruct();
        InputStruct punch = new InputStruct();
        InputStruct use = new InputStruct();
        InputStruct duck = new InputStruct();



        Skeleton skeleton;

        public KinectRun() {
            //FakeInput.Init();
            gas = FakeInput.GetInputStruct("W");
            left = FakeInput.GetInputStruct("A");
            right = FakeInput.GetInputStruct("d");
            jump = FakeInput.GetInputStruct("SPACE");
            punch = FakeInput.GetInputStruct("G");
            use = FakeInput.GetInputStruct("E");
            duck = FakeInput.GetInputStruct("LCONTROL");
        }

        public void SwapControls() {
            InputStruct swap;
            swap = left;
            left = right;
            right = swap;
        }

        public void Baseline() {
            LeftBaseline = skeleton.Joints[JointType.AnkleLeft].Position.Y;
            RightBaseline = skeleton.Joints[JointType.AnkleRight].Position.Y;
        }
       
        
        public override void UpdateSkeleton(Skeleton data) {
            RightCurrent = data.Joints[JointType.AnkleRight].Position.Y;
            LeftCurrent = data.Joints[JointType.AnkleLeft].Position.Y;

            RightKnee = data.Joints[JointType.KneeRight].Position.Y;
            LeftKnee = data.Joints[JointType.KneeLeft].Position.Y;

            skeleton = data;
        }

        public override void CheckMovement() {
            bool current = RightUp;

            if (Math.Abs(RightCurrent - RightBaseline) < 0.07f) {
                RightUp = false;
            } else {
                RightUp = true;
            }
            if (current != RightUp) {
                steps++;
                Run = true;
                start = DateTime.Now;
            }

            if (Math.Abs(LeftCurrent - LeftBaseline) < 0.07f) {
                LeftUp = false;
            } else {
                LeftUp = true;
            }

            if ((DateTime.Now - start).TotalMilliseconds > 750) {
                Run = false;
            }



            //Move to left or right
            if (skeleton != null  && Active) {
                MoveRight = CheckArms(skeleton.Joints[JointType.HandRight].Position, skeleton.Joints[JointType.ElbowRight].Position);
                MoveLeft = CheckArms(skeleton.Joints[JointType.HandLeft].Position, skeleton.Joints[JointType.ElbowLeft].Position);
                Jump = CheckJump();
                Punch = CheckPunch(skeleton.Joints[JointType.HandRight].Position, skeleton.Joints[JointType.HipCenter].Position);
                Use = CheckPunch(skeleton.Joints[JointType.HandLeft].Position, skeleton.Joints[JointType.HipCenter].Position);
                Duck = CheckDuck(skeleton.Joints[JointType.ShoulderCenter].Position, skeleton.Joints[JointType.HipCenter].Position);
            }

        }

        private bool CheckDuck(SkeletonPoint head, SkeletonPoint center) {
            if (Math.Abs(head.Y - center.Y) < .25f) {
                return true;
            } else {
                return false;
            }
        }

        //Says elbow, but we have been passing it HipCenter, hmm?
        private bool CheckPunch(SkeletonPoint hand, SkeletonPoint elbow) {
            if (Math.Abs(hand.Z - elbow.Z) > .4f) {
                return true;
            } else {
                return false;
            }
        }

        private bool CheckArms(SkeletonPoint outer, SkeletonPoint inner) {
            if ((Math.Abs(outer.X) - Math.Abs(inner.X)) > .25f) {
                return true;
            } else {
                return false;
            }
        } 

        private bool CheckJump() {

            if (Math.Abs(LeftCurrent - LeftBaseline) > .2f && Math.Abs(RightCurrent - RightBaseline) > .2f) {
                  Jump = true;
                JumpStart = DateTime.Now;
            } else if ((DateTime.Now - JumpStart).TotalMilliseconds > 750) {
                Jump = false;
            }

            return Jump;
        }

        public override void MovePlayer() {
            if (Run) {
                FakeInput.SimulateKeyDown(gas);
                HasGas = true;
            } else if (!Jump){
                FakeInput.SimulateKeyUp(gas);
                HasGas = false;
            }

            if (MoveLeft) {
                FakeInput.SimulateKeyDown(left);
            } else {
                FakeInput.SimulateKeyUp(left);
            }

            if (MoveRight) {
                FakeInput.SimulateKeyDown(right);
            } else {
                FakeInput.SimulateKeyUp(right);
            }

            if (Jump) {
                FakeInput.SimulateKeyDown(jump);
                FakeInput.SimulateKeyDown(gas);
            } else {
                FakeInput.SimulateKeyUp(jump);
            }

            if (Punch) {
                FakeInput.SimulateKeyDown(punch);
            } else {
                FakeInput.SimulateKeyUp(punch);
            }

            if (Use) {
                FakeInput.SimulateKeyDown(use);
            } else {
                FakeInput.SimulateKeyUp(use);
            }

            if (Duck) {
                FakeInput.SimulateKeyDown(duck);
            } else {
                FakeInput.SimulateKeyUp(duck);
            }


        }

        public override void SetKeys(string gaskey, string boostkey, string leanleft, string leanright, string _break, string _reverse) {
            throw new NotImplementedException();
        }
    }
}
